package com.example.librarymanagementproject2.service.impl;


import com.example.librarymanagementproject2.Common.exception.GlobalException;
import com.example.librarymanagementproject2.Common.utils.MinioUtil;
import com.example.librarymanagementproject2.mapper.UserMapper;
import com.example.librarymanagementproject2.model.document.BorrowRecordDocument;
import com.example.librarymanagementproject2.model.document.UserDocument;
import com.example.librarymanagementproject2.model.entity.BorrowRecord;
import com.example.librarymanagementproject2.model.entity.User;
import com.example.librarymanagementproject2.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.client.elc.NativeQueryBuilder;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @ClassName UserServiceImpl
 * @Description TODO
 * @Author Kx
 * @Date 2025/9/28 20:37
 * @Version 1.0
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    @Autowired
    /**
     * 密码编码组件
    */
    private PasswordEncoder passwordEncoder;

    @Autowired
    private MinioUtil minioUtil;

    @Autowired
    private ElasticsearchOperations elasticsearchOperations;

    /**
     * @author: kx
     * @date: 2025/10/28 9:50
     * @param pageNum : 页码
     * @param pageSize : 每页数量
     * @description: 分页查询所有用户信息
     */
    @Override
    public List<UserDocument> getAllUsers(Integer pageNum, Integer pageSize) {
        // 创建分页对象
        Pageable pageable = PageRequest.of(pageNum, pageSize);
        // 构建本地查询对象并分页
        NativeQuery query = NativeQuery.builder().withPageable(pageable).build();
        // 通过 search 方法查询所有的文档并返回命中结果集
        SearchHits<UserDocument> hits = elasticsearchOperations.search(query, UserDocument.class);
        hits.getSearchHits().forEach(hit -> {
            // 获取文档信息
            UserDocument userDocument = hit.getContent();
            // 获取用户临时访问头像图片路径
            String imageUrl = minioUtil.getImageUrl(userDocument.getImageUrl());
            // 设置用户临时访问头像图片路径
            userDocument.setImageUrl(imageUrl);
        });
        return hits.getSearchHits().stream().map(hit -> hit.getContent()).toList();
    }

    /**
     * @author: kx
     * @date: 2025/10/28 9:45
     * @param key : 搜索关键字
     * @param pageNum : 页码
     * @param pageSize : 每页数量
     * @description: 根据关键字分页查询用户信息
     */
    @Override
    public List<UserDocument> getUserById(String key, Integer pageNum, Integer pageSize) {
        // 创建分页对象
        Pageable pageable = PageRequest.of(pageNum, pageSize);
        // 构建查询构建器对象
        NativeQueryBuilder builder = NativeQuery.builder();
        // 设置 match 查询
        builder.withQuery(query -> query.match(match -> match.field("username").query(key))).withPageable(pageable).build();
        // 通过 search 方法查询所有的文档并返回命中结果集
        SearchHits<UserDocument> hits = elasticsearchOperations.search(builder.build(), UserDocument.class);
        hits.getSearchHits().forEach(hit -> {
            // 获取文档信息
            UserDocument userDocument = hit.getContent();
            // 获取用户临时访问头像图片路径
            String imageUrl = minioUtil.getImageUrl(userDocument.getImageUrl());
            // 设置用户临时访问头像图片路径
            userDocument.setImageUrl(imageUrl);
        });
        // 返回所有符合条件的文档信息
        return hits.getSearchHits().stream().map(hit -> hit.getContent()).toList();
    }

    /**
     * @param userId : 用户ID
     * @return java.util.List<org.example.model.entity.BorrowRecord>
     * @author: kx
     * @date: 2025/10/14 19:22
     * @description: 根据用户ID查询该用户的借阅记录
     */
    @Override
    public List<BorrowRecordDocument> getBorrowRecordsByUserId(Long userId) {
        // 创建查询构建器对象
        NativeQueryBuilder builder = NativeQuery.builder();
        // 设置 term 查询
        builder.withQuery(query -> query.term(term -> term.field("userId").value(userId)));
        // 通过 search 方法查询所有的文档并返回命中结果集
        SearchHits<BorrowRecordDocument> hits = elasticsearchOperations.search(builder.build(), BorrowRecordDocument.class);
        return hits.getSearchHits().stream().map(hit -> hit.getContent()).toList();
    }

    /**
     * @author: kx
     * @date: 2025/10/14 20:13
     * @param id : 用户ID
     * @param oldPassword : 旧密码
     * @param newPassword : 新密码
     * @description: 修改密码
    */
    @Override
    public void updatePassword(Long id, String oldPassword, String newPassword) {
        // 获取用户信息
        User user = userMapper.getUserById(id);
        // 判断用户信息是否为空
        if (user == null) {
            throw new GlobalException(404, "没有查询到该用户信息");
        }
        // 判断旧密码是否正确
        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            throw new GlobalException(400, "旧密码错误");
        }
        // 判断新密码是否与旧密码相同
        if (passwordEncoder.matches(newPassword, user.getPassword())) {
            throw new GlobalException(400, "新密码不能与旧密码相同");
        }
        // 加密新密码
        newPassword = passwordEncoder.encode(newPassword);
        try {
            // 修改密码
            userMapper.updatePassword(id, newPassword);
        } catch (Exception e) {
            throw new GlobalException(400, "修改密码失败");
        }
    }

    /**
     * @author: kx
     * @date: 2025/10/27 9:59
     * @param id : 用户ID
     * @param newAvatar : 新头像
     * @description: 修改用户头像
    */
    @Override
    public void updateAvatar(Long id, String newAvatar) {
        User user = userMapper.getUserById(id);

        // 判断用户是否存在
        if (user == null) {
            throw new GlobalException(404, "没有查询到该用户信息");
        }

        // 判断新头像是否为空
        if (newAvatar == null || newAvatar.trim().isEmpty()) {
            throw new GlobalException(400, "新头像不能为空");
        }

        try {
            // 修改头像
            userMapper.updateAvatar(id, newAvatar);
        } catch (Exception e) {
            throw new GlobalException(400, "修改头像失败" + e.getMessage());
        }
    }

    /**
     * @author: kx
     * @date: 2025/10/27 10:06
     * @param id : 用户ID
     * @description: 注销账号
    */
    @Override
    public void cancelAccount(Long id) {
        User user = userMapper.getUserById(id);

        // 判断用户是否存在
        if (user == null) {
            throw new GlobalException(404, "没有查询到该用户信息");
        }

        try {
            // 注销账号
            userMapper.cancelAccount(id);
        } catch (Exception e) {
            throw new GlobalException(400, "注销账号失败" + e.getMessage());
        }
    }
}
